<template>
  <div class="chat-content" id="service-chat">
    <template v-if="serviceList.length">
      <div class="grow-[1] h-0 relative" v-loading="state.loading">
        <template v-if="state.list.length == 0 && !state.loading">
          <div class="w-full h-full flex justify-center items-center">
            <el-empty description="暂无聊天记录" />
          </div>
        </template>
        <virtual-list
          v-if="state.list.length && !state.loading"
          ref="virtualScrollRef"
          :list="state.list"
          @is-scroll-bottom="isScrollBottom"
        >
          <template #header>
            <div class="h-[15px] w-full"></div>
          </template>
          <template #default="{ source }: Item">
            <div
              class="chat-box"
              :class="{
                'mine-chat-box': isMine(source)
              }"
            >
              <template v-if="!isMine(source)">
                <div class="w-[42px] h-[42px]">
                  <img
                    class="w-[42px] h-[42px] bg-[#fff] rounded-[42px]"
                    :src="netPath(source.Avatar)"
                  />
                </div>
              </template>
              <div
                class="flex-1 w-0"
                :class="{
                  'mr-[50px] ml-[10px]': !isMine(source),
                  'mr-[10px] ml-[50px]': isMine(source)
                }"
              >
                <div
                  :class="{
                    'flex justify-end': isMine(source)
                  }"
                >
                  <div class="chat-name">
                    {{ source.NickName }}
                    {{ formatDate(source.CreatedAt, "HH:mm:ss") }}
                  </div>
                </div>
                <div
                  :class="{
                    'flex justify-end': isMine(source)
                  }"
                >
                  <template v-if="source.MsgType == SocketMsgType.kefu_text_msg">
                    <div class="chat-message" v-html="formatContent(source.Msg)"></div>
                  </template>
                  <template v-if="source.MsgType == SocketMsgType.img_msg">
                    <div class="chat-message">
                      <div class="bg-[#f5f7fa] flex justify-center w-[220px] h-[144px]">
                        <ImgPreviewDialog :width="600" :src="source.Msg">
                          <el-image
                            class="h-full w-full"
                            fit="contain"
                            :src="netPath(source.Msg)"
                          />
                        </ImgPreviewDialog>
                      </div>
                    </div>
                  </template>
                </div>
              </div>
              <template v-if="isMine(source)">
                <div class="w-[42px] h-[42px] mt-[5px]">
                  <img
                    class="w-[42px] h-[42px] bg-[#fff] rounded-[42px]"
                    :src="netPath(source.Avatar)"
                  />
                </div>
              </template>
            </div>
          </template>
        </virtual-list>
        <div @click="scrollToBottom" v-if="showChatMore" class="show-chat-more">
          <span v-if="mainState.unreadMessage > 0">{{
            mainState.unreadMessage > 99 ? 99 : mainState.unreadMessage
          }}</span>
          <el-icon class="!text-white !text-[16px]"><ArrowDownBold /></el-icon>
        </div>
      </div>
      <div class="service-fotter">
        <chat-footer
          @send="(msg: string) => handleSend(msg, 22)"
          @upload="(path: string) => handleSend(path, 26)"
        />
      </div>
    </template>
    <div class="flex-1 flex items-center justify-center" v-else>
      <el-empty description="暂无数据"></el-empty>
    </div>
  </div>
</template>
<script setup lang="ts">
import ChatFooter from "./chat-footer.vue";
import VirtualList from "@/components/virtual-list.vue";

import $bus from "@/utils/bus";
import { storeToRefs } from "pinia";
import { formatDate, netPath } from "@/utils/common";
import { useUserStore } from "@/store/modules/user";
import { reqChatKefuList } from "@/api/main";
import { useServiceStore } from "@/store/modules/service";
import { cloneDeep } from "lodash-es";
import { useKefuStore } from "@/store/modules/kefu";
import { SocketMsgType } from "@/enums";

interface Item {
  source: ChatHistoryMo;
}

interface State {
  loading: boolean;
  page: number;
  pageSize: number;
  list: ChatHistoryMo[];
}

const mainState = inject("mainState")! as MainState;
const userStore = useUserStore();
const serviceStore = useServiceStore();
const socket = useKefuStore();
const { serviceList } = storeToRefs(serviceStore);
const { chatToken, userInfo } = storeToRefs(userStore);
const virtualScrollRef = ref();

const state = reactive<State>({
  loading: true,
  page: 1,
  pageSize: 100,
  list: []
});

const showChatMore = computed(() => {
  if (!mainState.autoScrollToBottom) {
    return true;
  } else {
    return false;
  }
});

// 获取历史消息
const getData = async () => {
  if (serviceList.value.length == 0) return;
  const curService = serviceList.value[mainState.serviceActive];
  if (!curService) return;
  try {
    state.loading = true;
    const res = await reqChatKefuList({
      Page: 1,
      PageSize: state.pageSize,
      UserId: Number(curService.UserId)
    });
    // 清空未读消息
    serviceStore.updateServiceItem(curService, true);
    state.loading = false;
    const list = res.data.List;
    list.reverse();
    state.list = list;
    mainState.autoScrollToBottom = true;
    nextTick(() => {
      virtualScrollRef.value?.scrollToBottom();
    });
  } catch (error) {
    state.loading = false;
    console.log(error);
  }
};

// 是否为自己
const isMine = (item: ChatHistoryMo) => {
  if (item.UserId === `r_${userInfo.value?.RoomId}`) {
    return true;
  }
  return false;
};

// 标签转义
function html2Escape(sHtml: string) {
  var temp: any = document.createElement("div");
  temp.textContent != null ? (temp.textContent = sHtml) : (temp.innerText = sHtml);
  var output = temp.innerHTML;
  temp = null;
  return output;
}

// 处理消息体
const formatContent = (content: string) => {
  let html = html2Escape(content);
  return html.replace(/\n/g, "<br />");
};

// 滚动到底部
const scrollToBottom = () => {
  virtualScrollRef.value?.scrollToBottom();
  mainState.unreadMessage = 0;
  const curService = serviceList.value[mainState.serviceActive];
  if (!curService) return;
  // 清空未读消息
  serviceStore.updateServiceItem(curService, true);
};

// 设置为是否滚动到底部
const isScrollBottom = (flag: boolean) => {
  mainState.autoScrollToBottom = flag;
};

// 发送消息
const handleSend = (content: string, msg_type: number) => {
  const cur = serviceList.value[mainState.serviceActive];
  const params = {
    token: chatToken.value, // 替换为实际用户的token
    roomName: cur?.Id + "",
    content,
    msgType: msg_type,
    sendType: "private" // 房间类型 (如需私聊，可设置为 PRIVATE)
  };
  socket.client?.emit("send_msg", params);
};

const watchSocket = () => {
  // 监听客服切换
  $bus.on("service-switch", () => {
    state.list = cloneDeep([]);
    getData();
  });
  // 监听房间消息
  $bus.on("kefu-msg", async data => {
    if (serviceList.value.length == 0) return;
    const cur = serviceList.value[mainState.serviceActive];
    if (cur.UserId == data.user_id || data.user_id == `r_${userInfo.value?.RoomId}`) {
      const params = {
        Avatar: data.avatar,
        ChatcontentId: cur?.Id as number,
        CreatedAt: data.time,
        Id: Date.now(),
        Msg: data.content,
        MsgType: data.msg_type,
        NickName: data.nick_name,
        Type: data.msg_type,
        UserId: data.user_id
      };
      let messages = cloneDeep(state.list);
      if (messages.length >= 600) {
        messages = messages.slice(200, messages.length + 1);
      }
      messages.push({
        ...params
      } as ChatHistoryMo);
      state.list = cloneDeep(messages);

      await nextTick();
      scrollToBottom();
    }
  });
};

onMounted(() => {
  watchSocket();
});

onUnmounted(() => {
  $bus.off("service-switch");
  $bus.off("kefu-msg");
});
</script>
<style scoped>
.chat-content {
  @apply h-full flex-1 w-0 bg-[#fff] flex flex-col justify-between;
  transition: all 0.3s ease;
}
.service-fotter {
  @apply h-[105px] w-full bg-[#fff];
}
.chat-name {
  @apply h-[18px] leading-[18px] px-[5px] rounded-[4px] inline-block text-[14px] mb-[4px];
  color: #878c94;
}
.chat-message {
  @apply bg-[#f4f7f8] inline-block p-[10px] mb-[10px] rounded-[6px] relative text-[14px] max-w-[450px];
  word-break: break-all;
  color: #666;
}
.show-chat-more {
  @apply absolute bottom-[5px] right-[15px] z-[50] cursor-pointer;
  @apply h-[40px] w-[40px] bg-[var(--el-color-primary)] rounded-[20px];
  @apply flex flex-col justify-center items-center text-white text-[14px];
}
</style>
<style lang="scss" scoped>
.chat-box {
  margin: 0 10px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  overflow: hidden;
  &:first-child {
    margin-top: 10px;
  }
}
.mine-chat-box {
  .chat-message {
    background-color: #dcf8c6;
  }
}
</style>
